/*
    Copyright 2006 Andrew Wilkinson <andrew@indiegigs.co.uk>

    This file is part of GL2x.

    GL2x is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    GL2x is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with GL2x; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define GLCLIENT
#include "gl_internal.h"

#define CHUNKSIZE 8

struct glpoly* newpoly() {
    struct glpoly* r = (struct glpoly*)GP2x_upper_memory_malloc(sizeof(struct glpoly));
    if(r == NULL) {
        fprintf(stderr, "GL2x: Failed to create space for a polygon. Have you run out of VRAM?\n");
        current_state->error = GL_OUT_OF_MEMORY;
        return NULL;
    }

    r->count = 0;
    r->allocsize = CHUNKSIZE;
    r->allow_delete = 1;
    void* mem = GP2x_upper_memory_malloc(sizeof(Vector)*CHUNKSIZE*3 + sizeof(Fixed)*2*CHUNKSIZE);
    r->vertices = (Vector*)GP2x_convert_ptr_to(mem);
    r->colours = (Vector*)GP2x_convert_ptr_to(mem + sizeof(Vector)*CHUNKSIZE);
    r->normals = (Vector*)GP2x_convert_ptr_to(mem + sizeof(Vector)*CHUNKSIZE*2);
    r->texcoords = (Fixed*)GP2x_convert_ptr_to(mem + sizeof(Vector)*CHUNKSIZE*3);
    if(r->vertices == NULL || r->colours == NULL || r->normals == NULL || r->texcoords == NULL) {
        unsigned int usedmemory;
        unsigned int usedblocks;
        unsigned int freeblocks;
        fprintf(stderr, "GL2x: Failed to create arrays for a polygon. Have you run out of VRAM?\n");
        GP2x_upper_memory_count(&usedmemory, &usedblocks, &freeblocks);
        fprintf(stderr, "GL2x: Allocated %i bytes in %i blocks. %i blocks free.\n", usedmemory, usedblocks, freeblocks);
        current_state->error = GL_OUT_OF_MEMORY;
        return NULL;
    }

    r->modelview = current_state->mvs->m;
    r->proj = current_state->pjs->m;

    return r;
}

void addvertex(struct glpoly* p, Vector* v) {
    if(p->allocsize == p->count) {
        Vector* nv;
        Fixed* nf;

        void* mem = GP2x_upper_memory_malloc(sizeof(Vector)*(p->allocsize + CHUNKSIZE)*3 + sizeof(Fixed)*2*(p->allocsize + CHUNKSIZE));
        nv = (Vector*)GP2x_convert_ptr_to(mem);
        memcpy(GP2x_convert_ptr_from2(nv), GP2x_convert_ptr_from2(p->vertices), sizeof(Vector)*p->allocsize);
        GP2x_upper_memory_free(GP2x_convert_ptr_from2(p->vertices));
        p->vertices = nv;

        nv = (Vector*)GP2x_convert_ptr_to(mem + sizeof(Vector)*(p->allocsize + CHUNKSIZE));
        memcpy(GP2x_convert_ptr_from2(nv), GP2x_convert_ptr_from2(p->colours), sizeof(Vector)*p->allocsize);
        GP2x_upper_memory_free(GP2x_convert_ptr_from(p->colours));
        p->colours = nv;

        nv = (Vector*)GP2x_convert_ptr_to(mem + sizeof(Vector)*(p->allocsize + CHUNKSIZE)*2);
        memcpy(GP2x_convert_ptr_from2(nv), GP2x_convert_ptr_from2(p->normals), sizeof(Vector)*p->allocsize);
        GP2x_upper_memory_free(GP2x_convert_ptr_from(p->normals));
        p->normals = nv;

        nf = (Fixed*)GP2x_convert_ptr_to(mem + sizeof(Vector)*(p->allocsize + CHUNKSIZE)*3);
        memcpy(GP2x_convert_ptr_from2(nv), GP2x_convert_ptr_from2(p->texcoords), sizeof(Vector)*p->allocsize);
        GP2x_upper_memory_free(GP2x_convert_ptr_from(p->texcoords));
        p->texcoords = nf;

        p->allocsize = p->allocsize + CHUNKSIZE;
    }

    ((Vector*)GP2x_convert_ptr_from(p->vertices))[p->count] = *v;
    ((Vector*)GP2x_convert_ptr_from(p->colours))[p->count] = current_state->colour;
    ((Vector*)GP2x_convert_ptr_from(p->normals))[p->count] = current_state->normal;
    ((Fixed*)GP2x_convert_ptr_from(p->texcoords))[p->count*2] = current_state->texcoord[0];
    ((Fixed*)GP2x_convert_ptr_from(p->texcoords))[p->count*2+1] = current_state->texcoord[1];

    p->count++;
}


